package com.qf.rbac.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qf.rbac.sys.entity.SysMenu;
import com.qf.rbac.sys.entity.SysRoleMenu;
import com.qf.rbac.sys.entity.SysUserRole;
import com.qf.rbac.sys.mapper.SysMenuMapper;
import com.qf.rbac.sys.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.rbac.sys.service.ISysRoleMenuService;
import com.qf.rbac.sys.service.ISysUserRoleService;
import com.qf.rbac.sys.service.ISysUserService;
import com.qf.rbac.utils.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单管理 服务实现类
 * </p>
 *
 * @author dongjl
 * @since 2022-04-16
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    ISysUserRoleService sysUserRoleService;
    @Autowired
    ISysRoleMenuService sysRoleMenuService;


    @Override
    public List<SysMenu> queryAllMenuByUserId(Long userId) {
        // 准备返回值
        ArrayList<SysMenu> sysMenus = new ArrayList<>();
        // 先查询用户角色信息
        List<SysUserRole> list = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId,userId));
        // 再根据角色信息查询菜单信息,查 role_menu
        list.forEach(sysUserRole -> {
            List<SysRoleMenu> roleMenus = sysRoleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId,sysUserRole.getRoleId()));
            roleMenus.forEach(sysRoleMenu -> {
                SysMenu sysMenu = this.getById(sysRoleMenu.getMenuId());
                sysMenus.add(sysMenu);
            });
        });
        return sysMenus;
    }

    @Override
    public List<String> queryAllPerms(Long userId) {
        List<SysMenu> sysMenus = queryAllMenuByUserId(userId);
        List<String> collect = sysMenus.stream().filter(sysMenu -> StringUtils.isNotBlank(sysMenu.getPerms())).map(sysMenu -> {
            return sysMenu.getPerms();
        }).distinct().collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<SysMenu> getUserMenuList(Long userId) {
        //系统管理员，拥有最高权限
        if(userId == Constants.SUPER_ADMIN){
           // 查询所有菜单信息
            List<SysMenu> allmenu = this.list();
            // 组织菜单层级关系
            return orgnizeByParentId(0l,allmenu);
        }

        //用户菜单列表
        List<SysMenu> menuList = this.queryAllMenuByUserId(userId);
        return orgnizeByParentId(0l,menuList);
    }

    /**
     *
     * @param parentId
     * @param allmenu
     * @return
     */
    private List<SysMenu> orgnizeByParentId(Long parentId, List<SysMenu> allmenu) {
        // 筛选出parentId对应的菜单
        List<SysMenu> menuList = allmenu.stream().filter(sysMenu -> sysMenu.getParentId().equals(parentId)).collect(Collectors.toList());
        // 给menuList中的所有菜单挂子菜单l
        if(menuList.size()>0){
            return populateChildMenu(menuList,allmenu);
        }else {
            return menuList;
        }
    }

    /**
     * 给list中的所有菜单寻找到子菜单
     * @param list 长度大于0
     * @param allmenu 所有菜单的集合
     * @return
     */
    private List<SysMenu> populateChildMenu(List<SysMenu> list, List<SysMenu> allmenu) {
        list.forEach(sysMenu -> {
            // 判断当前菜单有没有子菜单，如果没有，则返回
            List<SysMenu> childList = findChildMenu(sysMenu,allmenu);
            if (childList.size()>0) {
            // 如果有子菜单，则查找出所有子菜单，对子菜单进行寻找子菜单的递归调用
                populateChildMenu(childList,allmenu);
                // 挂子菜单到当前菜单
                sysMenu.setList(childList);
            }
        });
        return list;
    }

    /**
     * 查找子菜单
     * @param sysMenu 父菜单
     * @param allmenu 所有菜单
     * @return
     */
    private List<SysMenu> findChildMenu(SysMenu sysMenu, List<SysMenu> allmenu) {
        List<SysMenu> collect = allmenu.stream().filter(sysMenu1 -> sysMenu1.getParentId().equals(sysMenu.getMenuId())).collect(Collectors.toList());
        return collect;
    }


}
